package com.lujieni.redisson.controller;

import com.lujieni.redisson.entity.StudentPO;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Package: com.lujieni.redisson.controller
 * @ClassName: RedissonController
 * @Author: lujieni
 * @Description: 123
 * @Date: 2021-04-01 17:41
 * @Version: 1.0
 */
@RestController
public class RedissonController {

    @Autowired
    private RedissonClient redissonClient;

    @GetMapping("/testLock1")
    public String testLock1(){
        RLock lock = redissonClient.getLock("testLock1");
        lock.lock(10,TimeUnit.SECONDS);
        /*
            1.一个lock没有指定过期时间的话系统默认30秒
            2.存在多个lock以最后一个过期时间为主
            3.多个lock中只要有任一一个lock没有指定过期时间就会有看门狗
            4.看门狗默认30/3=10秒后启动,并把过期时间重置为30秒
         */
        lock.lock(25,TimeUnit.SECONDS);
        try{
            System.out.println("hello");
            TimeUnit.SECONDS.sleep(500000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "success";
    }

    /**
     * 不能瞎几把释放锁,别的线程加的锁只能别的线程解锁
     * attempt to unlock lock, not locked by current thread by node id: 5af26f5e-e2de-4d00-8ad0-c3a0e72e7bf7 thread-id: 62
     * @return
     */
    @GetMapping("/free")
    public String free(){
        RLock lock = redissonClient.getLock("testLock2");
        lock.unlock();
        return "ok";
    }

    @GetMapping("/testLock2")
    public String testLock2(){
        RLock lock = redissonClient.getLock("testLock2");
        lock.lock(); //多线程环境下执行lock.lock()会阻塞
        try{
            System.out.println("hello");
            TimeUnit.SECONDS.sleep(500000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "success";
    }

    @GetMapping("/testLock3")
    public String testLock3(){
        RLock lock = redissonClient.getLock("testLock3");
        if (lock.tryLock()) { //没有获得锁就立即返回
            try {
                System.out.println("hello");
                TimeUnit.SECONDS.sleep(500000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        return "success";
    }

    @GetMapping("/testLock4")
    public String testLock4() throws InterruptedException {
        RLock lock = redissonClient.getLock("testLock4");
        if (lock.tryLock(5,30,TimeUnit.SECONDS)) { //没有获得锁就立即返回
            try {
                System.out.println("hello");
                TimeUnit.SECONDS.sleep(500000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        return "success";
    }

    /**
     * @Description:
     *  1. bucket中只能放一个值
     *  2. bucket提供compareAndSet的乐观锁
     *  3. bucket中存对象会保留包名和类名 {"@class":"com.lujieni.redisson.entity.StudentPO","age":27,"name":"lujieni"},
     *     读取的时候强转就可以了
     *  4. bucket是以String类型存入redis中的
     *  5. edissonClient.getBucket("love")并不会存入redis,而是在 bucket.set(po);时写入
     * @return:
     * @Author: lujieni
     * @Date: 2021/4/2
     */
    @GetMapping("/testBucket")
    public String testBucket(){
        RBucket bucket = redissonClient.getBucket("love");
        StudentPO po = new StudentPO();
        po.setName("lujieni");
        po.setAge(27);
        bucket.set(po);
        System.out.println(bucket.get().getClass().getName());
        StudentPO studentPO = (StudentPO) bucket.get();
        System.out.println(studentPO);
        return "success";
    }

    private volatile int num = 0;


    /**
     * @Description: 测试原子性
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/4/6
     */
    @GetMapping("/testAtomic")
    public String testAtomic() throws InterruptedException {
       for(int i = 0; i < 100; i++){
            new Thread(()->{
                /*
                    乱序输出
                    try{
                        Thread.sleep(50);
                        System.out.println(++num);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                */

                /*
                    顺序输出
                 */
                RLock lock = redissonClient.getLock("lock");
                lock.lock(30,TimeUnit.SECONDS);
                try {
                    Thread.sleep(50);
                    System.out.println(++num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }).start();
       }
       return num+"";
    }


}